﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Xrm.Framework.Test.Unit;
using Microsoft.Xrm.Sdk.Workflow.Fakes;
using Microsoft.Xrm.Sdk.Fakes;

namespace Xrm.Framework.Test.Unit.Fakes
{
    /// <summary>
    /// Base Class for all Dynamics CRM 2011 Custom Workflow Activities using Fakes
    /// </summary>
    public abstract class WFActivityUnitTest : Xrm.Framework.Test.Unit.WFActivityUnitTest
    {
        #region Instance Variables

        private Guid _stubBusinessUnitId = Guid.NewGuid();
        private Guid _stubContextUserId = Guid.NewGuid();
        private Guid _stubCorrelationId = Guid.NewGuid();
        private Guid _stubInitiatingUserId = Guid.NewGuid();
        private DateTime _stubOperationCreatedOn = DateTime.Now;
        private Guid _stubOperationId = Guid.NewGuid();
        private Guid _stubOrganizationId = Guid.NewGuid();
        private Guid _stubPrimaryEntityId = Guid.NewGuid();
        private Guid _stubRequestId = Guid.NewGuid();

        #endregion

        #region Properties

        protected StubIWorkflowContext WorkflowContextStub
        {
            get;
            set;
        }

        protected StubIOrganizationService SystemOrganizationServiceStub
        {
            get;
            set;
        }

        protected StubIOrganizationService OrganizationServiceStub
        {
            get;
            set;
        }

        protected StubIOrganizationServiceFactory OrganizationServiceFactoryStub
        {
            get;
            set;
        }

        protected StubITracingService TracingServiceStub
        {
            get;
            set;
        }

        #endregion

        #region Constructors

        public WFActivityUnitTest()
            :base()
        {          
            Init();
        }

        #endregion

        #region Setup Stubs

        protected void Init()
        {
            this.SystemOrganizationServiceStub = new StubIOrganizationService();
            this.OrganizationServiceStub = new StubIOrganizationService();
            
            InitWorkflowContextMock(WorkflowContextStub);

            OrganizationServiceStub.CreateEntity = (entity) =>
            {
                return Guid.NewGuid();
            };

            SystemOrganizationServiceStub.CreateEntity = (entity) =>
            {
                return Guid.NewGuid();
            };

            OrganizationServiceFactoryStub.CreateOrganizationServiceNullableOfGuid = (id) =>
            {
                if (id == this.WorkflowContextStub.UserIdGet())
                {
                    return this.OrganizationServiceStub;
                }
                else if (id == null)
                    return this.SystemOrganizationServiceStub;
                else
                    return new StubIOrganizationService();
            };
        }

        private void InitWorkflowContextMock(StubIWorkflowContext mock)
        {
            mock.BusinessUnitIdGet = () => { return _stubBusinessUnitId;  };
            mock.CorrelationIdGet = () => { return _stubCorrelationId; };
            mock.DepthGet = () => { return 0; };
            mock.InitiatingUserIdGet = () => { return _stubInitiatingUserId; };
            mock.InputParametersGet = () => { return new ParameterCollection(); };
            mock.IsExecutingOfflineGet = () => { return false; };
            mock.IsInTransactionGet = () => { return false; };
            mock.IsOfflinePlaybackGet = () => { return false; };
            mock.IsolationModeGet = () => { return (int)PluginAssembyIsolationMode.Sandbox; };
            mock.MessageNameGet = () => { return string.Empty; };
            mock.ModeGet = () => { return (int)PluginMode.Synchronous; };
            mock.OperationCreatedOnGet = () => { return _stubOperationCreatedOn; };
            mock.OperationIdGet = () => { return _stubOperationId; };
            mock.OrganizationIdGet = () => { return _stubOrganizationId; };
            mock.OrganizationNameGet = () => { return string.Empty; };
            mock.OutputParametersGet = () => { return new ParameterCollection(); };
            mock.OwningExtensionGet = () => { return new EntityReference(); };
            mock.PostEntityImagesGet = () => { return new EntityImageCollection(); };
            mock.PreEntityImagesGet = () => { return new EntityImageCollection(); };
            mock.PrimaryEntityIdGet = () => { return Guid.NewGuid(); };
            mock.PrimaryEntityNameGet = () => { return string.Empty; };
            mock.RequestIdGet = () => { return _stubRequestId; };
            mock.SecondaryEntityNameGet = () => { return string.Empty; };
            mock.SharedVariablesGet = () => { return new ParameterCollection(); };
            mock.UserIdGet = () => { return _stubContextUserId; };
            mock.StageNameGet = () => { return string.Empty; };
            mock.WorkflowCategoryGet = () => { return ((int)WorkflowCategory.Workflow); };
        }

        protected override IWorkflowContext CreateWorkflowContext()
        {
            if (this.WorkflowContextStub == null)
                this.WorkflowContextStub = new StubIWorkflowContext();
            return this.WorkflowContextStub;
        }

        protected override ITracingService CreateTracingService()
        {
            if (this.TracingServiceStub == null)
                this.TracingServiceStub = new StubITracingService();
            return this.TracingServiceStub;
        }

        protected override IOrganizationServiceFactory CreateOrganizationServiceFactory()
        {
            if (this.OrganizationServiceFactoryStub == null)
                this.OrganizationServiceFactoryStub = new StubIOrganizationServiceFactory();
            return this.OrganizationServiceFactoryStub;
        }

        #endregion

    }
}
